#!/bin/bash -e
#
#   Neutron3529's Unity Game Plugin
#   Copyright (C) 2022 Neutron3529
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
############################################################################
#
#   * compile instructions: put this file and `utils.cs` in `steamapps`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x ${file}.cs
#   *     ./${file}.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

export GAME_NAME="${0%\.cs}"                                # might modify if the name mismatch.
export GAME_DIR="$GAME_NAME"                                # might be modified, but "$GAME_NAME" cover most of the cases.

export FILE_NAME="$0"
export ASSEMBLY="Assembly-CSharp"                           # might be modified
export UTILS="utils.cs"                                     # might be modified if you do not put utils.cs in the current dir.
export PLUGIN_ID="Neutron3529.Cheat"                        # should be modified
export NAMESPACE_ID="Neutron3529.Cheat"                     # should be modified
export GAME_BASE_DIR="common/$GAME_DIR"                     # should modify GAME_DIR instead since GAME_DIR == GAME_NAME is almost always true.

export IFS=$'\n' # to disable the annoying space.
export DOTNET="dotnet" # the location of the DOTNET executable file.
[ -z "$DOTNET_CSC_DLL" ] && export DOTNET_CSC_DLL=`\ls /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll` # In manjaro, the csc.dll is located in /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll

case $1 in
    V)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    v)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    VERBOSE) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    verbose) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    D)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    d)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    DEBUG)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    debug)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    *)       EXTRA_DEFINE=""                                               ;;
esac

_MODE__SELECT_=100

( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_) | sed s/%%NAMESPACE_ID%%/${NAMESPACE_ID}/g | sed s/%%PLUGIN_ID%%/${PLUGIN_ID}/g | $DOTNET $DOTNET_CSC_DLL -nologo -t:library \
  -r:"${GAME_BASE_DIR}/BepInEx/core/0Harmony.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Core.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.IL2CPP.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/UnhollowerBaseLib.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/Il2Cppmscorlib.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/Il2CppSystem.Core.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/Sirenix.Serialization.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.UI.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.CoreModule.dll" \
  $(for i in "${GAME_BASE_DIR}/BepInEx/unhollowed/$ASSEMBLY"*.dll ; do echo -e "-r:\"$i\"\n" ; done) \
  `[ -e "${GAME_BASE_DIR}/mono/Managed/netstandard.dll" ] && echo "-r:\"${GAME_BASE_DIR}/mono/Managed/netstandard.dll\""` \
  -r:"${GAME_BASE_DIR}/mono/Managed/System.dll" \
  -r:"${GAME_BASE_DIR}/mono/Managed/System.Core.dll" \
  -r:"${GAME_BASE_DIR}/mono/Managed/mscorlib.dll" \
  -out:"${GAME_BASE_DIR}/BepInEx/plugins/${FILE_NAME%.*}".dll \
  -optimize $EXTRA_DEFINE \
  - $UTILS && rm -f "${GAME_BASE_DIR}/BepInEx/config/${PLUGIN_ID}.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
        R) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        r) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        RANDOM) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        random) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        U) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        u) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        UPLOAD) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        upload) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        *) git commit -am "$2" ;;
    esac
    git push
fi
exit



using Il2CppSystem;
using Il2CppSystem.Linq;
using Il2CppSystem.Reflection;
using Il2CppSystem.Reflection.Emit;
using Il2CppSystem.Collections.Generic;

using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

namespace %%NAMESPACE_ID%%;

[BepInPlugin("%%PLUGIN_ID%%", "%%NAMESPACE_ID%%", "0.1.0")]
public class Cheat : Neutron3529.ModEntry {
    public Cheat() : base("%%PLUGIN_ID%%") {}
    public override void Awake() {
        base.Awake();
        // Mafi.Localization.LocalizationManager.EnableLocalization(); // 不知道为什么不加这一句会导致游戏变成纯英文
        // 主要逻辑放在`utils.cs`中，这里的Awake2只是为了以防万一
        // 目前来说，这个函数的唯一用途是用来“叮”……
        // 就像这样：
        logger("叮~修改器启动，请安心游戏");
    }
    [Desc("装备词条只可随机出最大数值")]
    class HuGan : Entry {
        [Desc("将属性词条改为全属性词条")]
        public static bool broadcast=true;
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_addAttribute),"createRandomEWE")]
        static void equipWordEffect_addAttribute(equipWordEffect_addAttribute __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_addLucky),"createRandomEWE")]
        static void equipWordEffect_addLucky(equipWordEffect_addLucky __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_xiXue),"createRandomEWE")]
        static void equipWordEffect_xiXue(equipWordEffect_xiXue __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_changeDamage),"createRandomEWE")]
        static void equipWordEffect_changeDamage(equipWordEffect_changeDamage __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
            if(broadcast){
                __instance.dType.Clear();
                __instance.dType.Add(Common.kungFuAttribute.all);
            }
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_changeDamageEx1),"createRandomEWE")]
        static void equipWordEffect_changeDamageEx1(equipWordEffect_changeDamageEx1 __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_addFightRunChance),"createRandomEWE")]
        static void equipWordEffect_addFightRunChance(equipWordEffect_addFightRunChance __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_subChangeRoleTime),"createRandomEWE")]
        static void equipWordEffect_subChangeRoleTime(equipWordEffect_subChangeRoleTime __instance){
            __instance.addMin=__instance.addMax;
            __instance._addMin=__instance._addMax;
        }
        [HarmonyPrefix, HarmonyPatch(typeof(equipWordEffect_addKungFuLv),"createRandomEWE")]
        static void equipWordEffect_addKungFuLv(equipWordEffect_addKungFuLv __instance){
            __instance.valueMin=__instance.valueMax;
            __instance._valueMin=__instance._valueMax;
        }
    }

    [Desc("坐骑随机固定最大值（不计算性格加成），且移动消耗置1，速度设置为最快")]
    class MaxMount : Entry {
        [HarmonyPatch(typeof(PlayerData.LeaderDynamicData),"addMount")]
        static void Prefix(Mount md){
            // // logger($"local_data: jgSpeedMax={md.local_data.jgSpeedMax}, jgSpeedMin={md.local_data.jgSpeedMin}, speedMax={md.local_data.speedMax}, speedMin={md.local_data.speedMin}, moveCostMax={md.local_data.moveCostMax}, moveCostMin={md.local_data.moveCostMin}");
            // // logger($"addLL {md.addLL}:{md.local_data.addLL}({md.local_data.addLLMin}-{md.local_data.addLLMax})");
            // // logger($"addTQ {md.addTQ}:{md.local_data.addTQ}({md.local_data.addTQMin}-{md.local_data.addTQMax})");
            // // logger($"addXW {md.addXW}:{md.local_data.addXW}({md.local_data.addXWMin}-{md.local_data.addXWMax})");
            // // logger($"energy {md.energy}:{md.local_data.energy}({md.local_data.energyMin}-{md.local_data.energyMax})");
            // // logger($"PQ_addLL {md.PQ_addLL}:{md.local_data.PQ_addLL}({md.local_data.PQ_addLLMin}-{md.local_data.PQ_addLLMax})");
            // // logger($"PQ_addTQ {md.PQ_addTQ}:{md.local_data.PQ_addTQ}({md.local_data.PQ_addTQMin}-{md.local_data.PQ_addTQMax})");
            // // logger($"PQ_addXW {md.PQ_addXW}:{md.local_data.PQ_addXW}({md.local_data.PQ_addXWMin}-{md.local_data.PQ_addXWMax})");
            // // logger($"weight {md.weight}:{md.local_data.weight}({md.local_data.weightMin}-{md.local_data.weightMax})");
            // // logger($"moveCost {md.moveCost}:{md.local_data.moveCost}({md.local_data.moveCostMin}-{md.local_data.moveCostMax})");
            // // logger($"speed {md.speed}:{md.local_data.speed}({md.local_data.speedMin}-{md.local_data.speedMax})");
            // // logger($"jgSpeed {md.jgSpeed}:{md.local_data.jgSpeed}({md.local_data.jgSpeedMin}-{md.local_data.jgSpeedMax})");
            // md.addLL=md.addLL+md.local_data.addLLMax-md.local_data.addLL;md.local_data.addLL=md.local_data.addLLMax;
            // md.addTQ=md.addTQ+md.local_data.addTQMax-md.local_data.addTQ;md.local_data.addTQ=md.local_data.addTQMax;
            // md.addXW=md.addXW+md.local_data.addXWMax-md.local_data.addXW;md.local_data.addXW=md.local_data.addXWMax;
            // md.energyMax=md.energyMax+md.local_data.energyMax-md.local_data.energyMax;md.local_data.energyMax=md.local_data.energyMax;
            // md.PQ_addLL=md.PQ_addLL+md.local_data.PQ_addLLMax-md.local_data.PQ_addLL;md.local_data.PQ_addLL=md.local_data.PQ_addLLMax;
            // md.PQ_addTQ=md.PQ_addTQ+md.local_data.PQ_addTQMax-md.local_data.PQ_addTQ;md.local_data.PQ_addTQ=md.local_data.PQ_addTQMax;
            // md.PQ_addXW=md.PQ_addXW+md.local_data.PQ_addXWMax-md.local_data.PQ_addXW;md.local_data.PQ_addXW=md.local_data.PQ_addXWMax;
            // md.weight=md.weight+md.local_data.weightMax-md.local_data.weight;md.local_data.weight=md.local_data.weightMax;
            //
            // md.moveCost=md.moveCost+md.local_data.moveCostMin-md.local_data.moveCost;md.local_data.moveCost=md.local_data.moveCostMin;
            // md.jgSpeed=md.jgSpeed+md.local_data.jgSpeedMin-md.local_data.jgSpeed;md.local_data.jgSpeed=md.local_data.jgSpeedMin;
            // md.speed=md.speed+md.local_data.speedMin-md.local_data.speed;md.local_data.speed=md.local_data.speedMin;
            // logger($"local_data: jgSpeedMax={md.local_data.jgSpeedMax}, jgSpeedMin={md.local_data.jgSpeedMin}, speedMax={md.local_data.speedMax}, speedMin={md.local_data.speedMin}, moveCostMax={md.local_data.moveCostMax}, moveCostMin={md.local_data.moveCostMin}");
            md.addLL=md.local_data.addLLMax;
            md.addTQ=md.local_data.addTQMax;
            md.addXW=md.local_data.addXWMax;
            md.energyMax=md.local_data.energyMax;
            md.PQ_addLL=md.local_data.PQ_addLLMax;
            md.PQ_addTQ=md.local_data.PQ_addTQMax;
            md.PQ_addXW=md.local_data.PQ_addXWMax;
            md.weight=md.local_data.weightMax;

            md.moveCost=1;
            md.jgSpeed=0.1f;
            md.speed=0.1f;
        }
        // [HarmonyPatch(typeof(Mount),"local_data",MethodType.Getter)]
        // static MountData Postfix(MountData data){
        //     logger($"local_data: data.addLL={data.addLL}, data.addTQ={data.addTQ}, data.addXW={data.addXW}, data.moveCostMax={data.moveCostMax}, data.moveCostMin={data.moveCostMin}");
        //     data.addLLMin=data.addLLMax;
        //     data.addTQMin=data.addTQMax;
        //     data.addXWMin=data.addXWMax;
        //     data.energyMin=data.energyMax;
        //     data.PQ_addLLMin=data.PQ_addLLMax;
        //     data.PQ_addTQMin=data.PQ_addTQMax;
        //     data.PQ_addXWMin=data.PQ_addXWMax;
        //     data.weightMin=data.weightMax;
        //
        //     data.moveCostMax=data.moveCostMin;
        //     data.jgSpeedMax=data.jgSpeedMin;
        //     data.speedMax=data.speedMin;
        //     return data;
        // }
        // [HarmonyPostfix, HarmonyPatch(typeof(MountData),MethodType.Constructor,new Type[]{})]
        // // [HarmonyPatch(typeof(Mount),"local_data",MethodType.Getter)]
        // static void Postfixz(MountData __instance){
        //     logger($"after: __instance.addLL={__instance.addLL}, __instance.addTQ={__instance.addTQ}, __instance.addXW={__instance.addXW}, __instance.moveCostMax={__instance.moveCostMax}, __instance.moveCostMin={__instance.moveCostMin}");
        //     __instance.addLLMin=__instance.addLLMax;
        //     __instance.addTQMin=__instance.addTQMax;
        //     __instance.addXWMin=__instance.addXWMax;
        //     __instance.energyMin=__instance.energyMax;
        //     __instance.PQ_addLLMin=__instance.PQ_addLLMax;
        //     __instance.PQ_addTQMin=__instance.PQ_addTQMax;
        //     __instance.PQ_addXWMin=__instance.PQ_addXWMax;
        //     __instance.weightMin=__instance.weightMax;
        //
        //     __instance.moveCostMax=__instance.moveCostMin;
        //     __instance.jgSpeedMax=__instance.jgSpeedMin;
        //     __instance.speedMax=__instance.speedMin;
        // }
        //
        // [HarmonyPostfix, HarmonyPatch(typeof(MountData),MethodType.Constructor,new Type[]{typeof(IntPtr)})]
        // // [HarmonyPatch(typeof(Mount),"local_data",MethodType.Getter)]
        // static void Postfixx(MountData __instance){
        //     logger($"before(called twice): __instance.addLL={__instance.addLL}, __instance.addTQ={__instance.addTQ}, __instance.addXW={__instance.addXW}, __instance.moveCostMax={__instance.moveCostMax}, __instance.moveCostMin={__instance.moveCostMin}");
        //     __instance.addLLMin=__instance.addLLMax;
        //     __instance.addTQMin=__instance.addTQMax;
        //     __instance.addXWMin=__instance.addXWMax;
        //     __instance.energyMin=__instance.energyMax;
        //     __instance.PQ_addLLMin=__instance.PQ_addLLMax;
        //     __instance.PQ_addTQMin=__instance.PQ_addTQMax;
        //     __instance.PQ_addXWMin=__instance.PQ_addXWMax;
        //     __instance.weightMin=__instance.weightMax;
        //
        //     __instance.moveCostMax=__instance.moveCostMin;
        //     __instance.jgSpeedMax=__instance.jgSpeedMin;
        //     __instance.speedMax=__instance.speedMin;
        // }
    }
    // [Desc("炼制物品默认满熟练度")]
    // class makeEquipUnit_max_totalMakeNumber : Entry {
    //     [HarmonyPatch(typeof(PlayerData.makeEquipUnit),"totalMakeNumber", MethodType.Getter)]
    //     static int Postfix(int res)=>Math.Max(res,100);
    // }
    [HarmonyPatch(typeof(equipWordEffect_addAttribute),"createRandomEWE")]
    class WordEffect_addAttribute : Entry {
        [Desc("装备词条随机属性倍率")]
        public static float val=10f;
        static equipWordEffect_addAttribute Postfix(equipWordEffect_addAttribute ret){
            ret.value=Mathf.Max(ret.addMax, ret.value)*val;return ret;
        }
    }
    [HarmonyPatch(typeof(equipWordEffect_addLucky),"createRandomEWE")]
    class WordEffect_addLucky : Entry {
        [Desc("装备词条随机幸运属性倍率")]
        public static int val=10;
        static equipWordEffect_addLucky Postfix(equipWordEffect_addLucky ret){
            ret.value=Mathf.Max(ret.addMax, ret.value)*val;return ret;
        }
    }
    [HarmonyPatch(typeof(equipWordEffect_xiXue),"createRandomEWE")]
    class WordEffect_xiXue : Entry {
        [Desc("装备词条随机吸血倍率")]
        public static int val=10;
        static equipWordEffect_xiXue Postfix(equipWordEffect_xiXue ret){
            ret.value=Math.Max(ret.addMax, ret.value)*val;return ret;
        }
    }
    [HarmonyPatch(typeof(equipWordEffect_changeDamage),"createRandomEWE")]
    class WordEffect_changeDamage : Entry {
        [Desc("装备词条随机伤害属性倍率")]
        public static float val=10f;
        static equipWordEffect_changeDamage Postfix(equipWordEffect_changeDamage ret){
            ret.value=Mathf.Max(ret.addMax, ret.value)*val;return ret;
        }
    }
    [HarmonyPatch(typeof(equipWordEffect_changeDamageEx1),"createRandomEWE")]
    class WordEffect_changeDamageEx1 : Entry {
        [Desc("装备词条随机伤害属性Ex1倍率")]
        public static float val=10f;
        static equipWordEffect_changeDamageEx1 Postfix(equipWordEffect_changeDamageEx1 ret){
            ret.value=Mathf.Max(ret.addMax, ret.value)*val;return ret;
        }
    }
    // [HarmonyPatch(typeof(PlayerData.acSkillUnit),"acSkillExp", MethodType.Setter)]
    // class acSkillUnit_acSkillExp : Entry {
    //     [Desc("生活技能经验倍率")] // 我也不知道这是什么
    //     public static int val=10;
    //     static void Prefix(ref int value)=>value*=val;
    // }
    [HarmonyPatch(typeof(PlayerData.SkillSt),"Add")]
    class SkillSt_Add : Entry {
        [Desc("生活技能经验倍率")]
        public static int mul=10;
        static void Prefix(ref int val)=>val*=mul;
    }
    [HarmonyPatch(typeof(PlayerData.LeaderDynamicData),"addMPUnitExp")]
    class LeaderDynamicData_addMPUnitExp : Entry {
        [Desc("门派好感倍率（感谢Gmhaxxing的CT脚本）")]
        public static int mul=10;
        static void Prefix(ref int exp)=>exp*=mul;
    }
    [HarmonyPatch(typeof(PlayerData.LeaderDynamicData),"addSLUnitExp")]
    class LeaderDynamicData_addSLUnitExp : Entry {
        [Desc("势力好感倍率（感谢Gmhaxxing的CT脚本）")]
        public static int mul=10;
        static void Prefix(ref int exp)=>exp*=mul;
    }
    [Desc("物品个数不减（感谢Gmhaxxing的CT脚本）",-1)]
    [HarmonyPatch(typeof(ItemBase),"number", MethodType.Setter)]
    class ItemBase_number : Entry {
        static void Prefix(ItemBase __instance, ref int value)=>value=Math.Max(value, __instance.number);
    }
    [Desc("禁止ItemBase.Discard（感谢Gmhaxxing的CT脚本）（默认不生效，借以丢弃物品）",-1)]
    [HarmonyPatch(typeof(ItemBase),"Discard")]
    class ItemBase_Discard : Entry {
        static bool Prefix()=>false;
    }
    // [Desc("龙舟第一名可获得全部参赛奖励")]
    // [HarmonyPatch(typeof(NPCA_EventLZ),"Items_1st", MethodType.Getter)]
    // class NPCA_EventLZ_gold_1st : Entry {
    //     static List<ItemBase> Postfix(List<ItemBase> res, NPCA_EventLZ __instance)=>__instance.Items_1st_all;
    // }
    // [HarmonyPatch(typeof(ServerHG),"hgfenjie")]
    // class ServerHG_hgfenjie : Entry {
    //     [Desc("魂晶分解倍率（感谢Gmhaxxing的CT脚本）")]
    //     public static int mul=10;
    //     static void Prefix(ref int exp)=>exp*=mul;
    // }
}
